package cn.xawl.interview.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author lh
 * @date 2020/08/27 13:23:42
 *
 * synchronized和Lock的区别
 *1 . synchronized是Java关键字，在JVM层面利用monitor实现；Lock是API层面。
 * 2. 使用方法：synchronized不需要手动释放锁，执行完代码后会自动释放锁；Lock需要手动释放锁unlock，否则会出现死锁现象。
 * 3. 等待是否可中断：synchronized不可以中断，只能等待运行完毕或者抛出异常退出；Lock可以设置超时时间或者调用interrupt方法手动中断。
 * 4. 加锁是否公平：synchronized是非公平锁；ReentrantLock默认非公平锁，可以设置为公平锁。
 * 5. 绑定多个条件Condition：synchronized没有；ReentrantLock可以利用Condition实现精确唤醒某个线程。
 *
 *      实现多线程之间按顺序调用：A线程打印A5次，B线程打印B10次，C线程打印C15次
 *      循环执行10次
 **/
public class SynchronizedAndLockDemo {

    private static int number = 1;

    public static void main(String[] args) {

        Lock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();
        for (int i = 0; i < 10; i++) {

            print(lock, condition1, condition2, 5, 1, "A");
            print(lock, condition2, condition3, 10, 2, "B");
            print(lock, condition3, condition1, 15, 3, "C");

        }

    }

    private static void print(Lock lock, Condition from, Condition to, int cishu, int threadIndex, String threadName) {
        new Thread(() -> {
            lock.lock();
            try {
                while (number != threadIndex) {
                    from.await();
                }
                for (int j = 0; j < cishu; j++) {
                    System.out.println(Thread.currentThread().getName() + "\t" + j);
                }
                if (number == 3) {
                    number = 1;
                } else {
                    number++;
                }
                to.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }, threadName).start();
    }

}
